package com.freight.common.core.interceptor;

import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.freight.common.core.constant.Constants;
import com.freight.common.core.utils.SecurityUtils;
import com.freight.common.core.utils.StringUtils;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.*;

import java.util.List;

/**
 * 租户拦截器
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class RybTenantInterceptor extends TenantLineInnerInterceptor {

	/**
	 * 租户处理器
	 */
	private TenantLineHandler tenantLineHandler;

	@Override
	public void setTenantLineHandler(TenantLineHandler tenantLineHandler) {
		super.setTenantLineHandler(tenantLineHandler);
		this.tenantLineHandler = tenantLineHandler;
	}

	/**
	 * 处理 PlainSelect
	 */
	@Override
	protected void processPlainSelect(PlainSelect plainSelect) {
		FromItem fromItem = plainSelect.getFromItem();
		Expression where = plainSelect.getWhere();

		//processWhereSubSelect(where);
		if (fromItem instanceof Table) {
			Table fromTable = (Table) fromItem;
			String tenantId = SecurityUtils.getTenantId();
			// 如果不是主租户
			if(StringUtils.isNotBlank(tenantId) && !Constants.ADMIN_TENANT_ID.equals(tenantId)) {
				// 判断表名是否需要过滤
				if (!tenantLineHandler.ignoreTable(fromTable.getName())) {
					plainSelect.setWhere(builderExpression(where, fromTable));
				}
			}
		} else {
			processFromItem(fromItem);
		}
		//#3087 github
		List<SelectItem> selectItems = plainSelect.getSelectItems();
		if (selectItems != null && selectItems.size() > 0) {
			selectItems.forEach(this::processSelectItem);
		}
		List<Join> joins = plainSelect.getJoins();
		if (joins != null && joins.size() > 0) {
			joins.forEach(j -> {
				processJoin(j);
				processFromItem(j.getRightItem());
			});
		}
	}

	/**
	 * delete update 语句 where 处理
	 */
	@Override
	protected BinaryExpression andExpression(Table table, Expression where) {
		EqualsTo equalsTo = builderEqualsTo(table);
		if (null != where) {
			if (where instanceof OrExpression) {
				return new AndExpression(equalsTo, new Parenthesis(where));
			} else {
				return new AndExpression(equalsTo, where);
			}
		}
		return equalsTo;
	}

	/**
	 * 子查询解析支持
	 */
	protected void processSelectItem(SelectItem selectItem) {
		if (selectItem instanceof SelectExpressionItem) {
			SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem;
			if (selectExpressionItem.getExpression() instanceof SubSelect) {
				processSelectBody(((SubSelect) selectExpressionItem.getExpression()).getSelectBody());
			} else if (selectExpressionItem.getExpression() instanceof Function) {
				ExpressionList parameters = ((Function) selectExpressionItem.getExpression()).getParameters();
				if (parameters != null) {
					parameters.getExpressions().forEach(expression -> {
						if (expression instanceof SubSelect) {
							processSelectBody(((SubSelect) expression).getSelectBody());
						}
					});
				}
			}
		}
	}

	/**
	 * 获取条件表达式
	 *
	 * @param table 表
	 */
	public EqualsTo builderEqualsTo(Table table) {
		//获得条件表达式
		EqualsTo equalsTo = new EqualsTo();
		Expression leftExpression = this.getAliasColumn(table);
		Expression rightExpression = tenantLineHandler.getTenantId();
		// 若是超管则不进行过滤
		//if (doTenantFilter(table.getName())) {
			leftExpression = rightExpression = new StringValue(StringPool.ONE);
		//}

		equalsTo.setLeftExpression(leftExpression);
		equalsTo.setRightExpression(rightExpression);
		return equalsTo;
	}

}
